import cv2
import mediapipe as mp
from utils.get_relative import cal_relative
from utils.load_model import load_pth, PointNetwork
from utils.get_xy import get_pxy
from utils.get_distance import get_all_distances
from pathlib import Path
import threading
import queue
from game import run
import numpy as np
import torch
import torch.nn.functional as F
def start_record(coord_queue):
    point_model = PointNetwork()
    model = load_pth(point_model, 'models/points-v5.pth')
    mp_hands = mp.solutions.hands
    hands = mp_hands.Hands(static_image_mode=False, max_num_hands=2, min_detection_confidence=0.5)
    mp_drawing = mp.solutions.drawing_utils
    label_dict = {0: "one", 1: "two", 2: "three", 3: "four", 4: "five", 5: "six", 6: "seven", 7: "eight", 8: "nine", 9: "ok"}

    # 尝试打开摄像头
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print("无法打开摄像头")
        exit()

    # 设置显示窗口的宽度和高度
    display_width = 1000
    display_height = 800

    # 创建一个可调整大小的窗口
    cv2.namedWindow('Hand Landmark Detection', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('Hand Landmark Detection', display_width, display_height)

 
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            print("无法读取帧")
            break

        # 水平翻转图像
        frame = cv2.flip(frame, 1)

        # 将图像从 BGR 转换为 RGB
        image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        image.flags.writeable = False

        # 处理图像以检测手部关键点
        results = hands.process(image)

        # 将图像从 RGB 转换回 BGR
        image.flags.writeable = True
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

        # 绘制手部关键点和连接线
        if results.multi_hand_landmarks:
            for hand_landmarks in results.multi_hand_landmarks:
                xyz_dis = get_all_distances(hand_landmarks)
                input_tensor = torch.tensor(xyz_dis, dtype=torch.float32).unsqueeze(0)
                output = model(input_tensor)
                probabilities = F.softmax(output, dim=1)
                max_value = torch.max(probabilities).item()
                if max_value < 0.99:
                    print(f"Predicted Label: None")
                else:
                    max_prob_index = torch.argmax(probabilities, dim=1).item()
                    predicted_label = label_dict[max_prob_index]
                    if predicted_label == "one":
                        x, y = get_pxy(hand_landmarks, 0)
                        try:
                            coord_queue.put_nowait((int(x * display_width), int(y * display_height)))
                        except queue.Full:
                            # 处理队列已满的情况，例如打印日志或跳过
                            print("队列已满，跳过本次插入")
                    elif predicted_label == "two":
                        try:
                            coord_queue.put_nowait(1)
                        except queue.Full:
                            # 处理队列已满的情况，例如打印日志或跳过
                            print("队列已满，跳过本次插入")
                mp_drawing.draw_landmarks(
                    image, hand_landmarks, mp_hands.HAND_CONNECTIONS)

        # 调整图像大小
        resized_image = cv2.resize(image, (display_width, display_height))

        # 显示图像
        cv2.imshow('Hand Landmark Detection', resized_image)

        if cv2.waitKey(5) & 0xFF == 27:  # 按下 ESC 键退出
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    # 创建队列用于线程间通信
    coord_queue = queue.Queue()
    # 创建并启动手势检测线程
    gesture_thread = threading.Thread(target=start_record, args=(coord_queue,))
    gesture_thread.start()

    # 创建并启动游戏控制线程
    game_thread = threading.Thread(target=run, args=(coord_queue,))
    game_thread.start()

    # 等待手势检测线程结束
    gesture_thread.join()
    # 等待游戏控制线程结束
    game_thread.join()